package com.putable.nmc.dmv.demo;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.InputMismatchException;

import com.putable.nmc.world.CIT;
import com.putable.nmc.world.World;

/**
 * A tiny demonstration class showing some of how to construct and interact with
 * a com.putable.nmc.world.World object.
 * 
 * <p>
 * Feel free to copy or modify any code in this class.
 * 
 * @author ackley
 * @version 0.9
 * 
 */

public class Demo {
	private World world;
    
	/**
     * Build a Demo object.  If the length of the args array is 0, a
     * 'default' world is built, otherwise, the first argument is
     * treated as a filename and an attempt is made to load that
     * file as a world configuration.
     * 
     * @param args 
	 */
    public Demo(String[] args) {
        if (args.length == 0) world = new World();  // Make a default world
        else {
            try {
                if (args.length != 2) 
                    throw new InputMismatchException("Need exactly two files");

                FileReader readStaff = new FileReader(args[0]);
                FileReader readWorld = new FileReader(args[1]);
                world = new World(readStaff, readWorld);
            } 
            catch (FileNotFoundException e) {
                System.err.println("Can't read "+args[0]);
                e.printStackTrace();
                System.exit(1);
            }
            catch (InputMismatchException e) {
                System.err.println("Problem loading "+args[0]);
                e.printStackTrace();
                System.exit(2);
            }
        }
	}
    /**
     * A method demonstrating acquiring and returning CIT objects from a World.
     * <p>
     * In a real simulation we'd get our NMCDMV object all set up, and then start
     * calling the world to feed is 'CIT's -- 'Customer Information Tokens' from
     * which we would build our actual Customers that we'd handle in our NMCDMV
     * <p>
     * But here, since we're just a weenie little demo of how to talk to the
     * world (a 'simulated simulation'?), we'll just start calling for CIT's,
     * printing out some info from them, and then reporting back to the world
     * that we failed to serve them -- haw!
     * <p>
     * One tricky point about CIT's: We tell them what time it is 'now', but the
     * token we get back will specify an arrival time sometime in the future.
     * Given such a CIT, it's our job to: (1) Make sure that the customer we
     * make actually arrives at token.getTimeArrived(), not at the current
     * 'now', AND (2) Call the world's getNextCIT method again precisely at
     * token.getTimeArrived(), for it to once again tell us the next customer to
     * arrive.
     * 
     * @return true if we 'won' the simulation, in the sense of making enough
     *         money to stay open without causing too many customers to
     *         complain.
     * 
     */
    public boolean run() {

        double clock = 0.0;       // 0.0 is 8:00:00AM sharp!
        while (true) {

            CIT cit = world.getNextCIT(clock);
            if (cit == null) break;     // Miller time!

            // Let's dig out some info 
            System.out.println("A "+cit.getType()+
                               " will arrive at: "+cit.getArrivalTime()+
                               " to do a: "+cit.getTask()+" value task"+
                               " and will punt at: " +cit.getGiveupTime());

            // Here we'd build some class derived from Customer
            // and throw it in our PQueue with a priority of
            // getTimeArrived and such.  For now, since we
            // don't have anything else to do, we'll just jump
            // the clock and keep going..
            
            clock = cit.getArrivalTime();
            
            cit.setEntered(true);
            
            // Let's pretend we immediately PO'ed the customer
            // somehow, so (s)he leaves right away.  
            
            // When we take possession of a CIT, it is our (first)
            // responsibility to see if there's room in the building
            // for the corresponding customer.  If there _IS_ room, we
            // must call cit.setEntered(true).  If we fail to do so,
            // when the cit is interviewed upon return to the World,
            // it will be recorded as 'Turned away' in the statistics.
            
            // Here, since we don't have a DMV, we're not going to
            // call setEntered, so all our customers will be recorded
            // as having been turned away.
            
            world.exitInterview(cit);
        }
        
        // OK, no more customers.  Let's see how we did, heh heh.
        Writer out = new StringWriter();
        boolean weWon = world.getScore(out);
        System.out.println(out.toString());
        return weWon;
	}

    /**
     * A mainline to drive the demo
     * 
     * @param args
     *            Either an empty array, to build a default world, or an array
     *            whose first element is the name of a file to load a world
     *            configuration from.
     */
    public static void main(String[] args) {
		Demo s = new Demo(args);
		System.exit(s.run()?0:3);
        
	}
}
